#pragma once
#include <map>
#include <vector>
#include "base/core/com_define.h"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4005)
#endif
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#ifdef _MSC_VER
#pragma warning(pop)
#endif

const char* GetJsonStringValue(const rapidjson::Document& docjson, const char* key);
bool        GetJsonInt32Value(const rapidjson::Document& docjson, const char* key, int32_t& val);
bool        GetJsonUInt32Value(const rapidjson::Document& docjson, const char* key, uint32_t& val);
bool        GetJsonInt64Value(const rapidjson::Document& docjson, const char* key, int64_t& val);
bool        GetJsonUInt64Value(const rapidjson::Document& docjson, const char* key, uint64_t& val);
bool        GetJsonFloatValue(const rapidjson::Document& docjson, const char* key, float& val);
bool        GetJsonDoubleValue(const rapidjson::Document& docjson, const char* key, double& val);
bool        GetJsonBoolValue(const rapidjson::Document& docjson, const char* key, bool& val);

bool        GetJsonInt32Value(const rapidjson::Document& docjson, const char* key, int32_t defaultVal, int32_t& val);
bool        GetJsonUInt32Value(const rapidjson::Document& docjson, const char* key, uint32_t dafaultVal, uint32_t& val);
bool        GetJsonBoolValue(const rapidjson::Document& docjson, const char* key, bool defaultVal, bool& val);
bool        GetJsonTimeStampToUnixSec(const rapidjson::Document& docjson, const char* key, uint64_t& val);

const char* GetJsonStringValue(const rapidjson::Value& docjson, const char* key);
bool        GetJsonInt32Value(const rapidjson::Value& docjson, const char* key, int32_t& val);
bool        GetJsonUInt32Value(const rapidjson::Value& docjson, const char* key, uint32_t& val);
bool        GetJsonBoolValue(const rapidjson::Value& docjson, const char* key, bool& val);

bool        GetJsonInt32Value(const rapidjson::Value& docjson, const char* key, int32_t defaultVal, int32_t& val);
bool        GetJsonBoolValue(const rapidjson::Value& docjson, const char* key, bool defaultVal, bool& val);

class JsonObject;
class JsonArray 
{
    friend class JsonObject;
public:
    JsonArray(rapidjson::Document* doc);
    ~JsonArray();

    bool PushString(const char* val);
    bool PushString(const std::string& val);
    bool PushInt32(int32_t val);
    bool PushUInt32(uint32_t val);
    bool PushInt64(int64_t val);
    bool PushUInt64(uint64_t val);
    bool PushFloat(float val);
    bool PushDouble(double val);
    bool PushBool(bool val);
    bool PushArray(int32_t array[], size_t size);
    bool PushArray(uint32_t array[], size_t size);
    bool PushArray(char* array[], size_t size);
    bool PushArray(const JsonArray& val);
    bool PushVector(const std::vector<int32_t>& val);
    bool PushVector(const std::vector<uint32_t>& val);
    bool PushVector(const std::vector<std::string>& val);
    bool PushObject(const JsonObject& obj);

    bool ToString(std::string& str) const;
    bool ToString(char* buf, size_t len) const;
    std::string ToString() const;
    uint32_t Size() const;

    rapidjson::Document* GetDoc();

protected:
    rapidjson::Document* m_doc;
    rapidjson::Value*    m_value;
};


class JsonObject 
{
    friend class JsonArray;
public:
    JsonObject(rapidjson::Document* doc);
    ~JsonObject();

    bool AddString(const char* key, const char* val);
    bool AddString(const char* key, const std::string& val);
    bool AddInt32(const char* key, int32_t val);
    bool AddUInt32(const char* key, uint32_t val);
    bool AddInt64(const char* key, int64_t val);
    bool AddUInt64(const char* key, uint64_t val);
    bool AddFloat(const char* key, float val);
    bool AddDouble(const char* key, double val);
    bool AddBool(const char* key, bool val);
    bool AddArray(const char* key, const JsonArray& array);
    bool AddObject(const char* key, const JsonObject& obj);
    bool AddMap(const std::map<std::string, int32_t>& val);
    bool AddMap(const std::map<std::string, uint32_t>& val);
    bool AddMap(const std::map<std::string, std::string>& val);

    bool ToString(std::string& str) const;
    bool ToString(char* buf, size_t len) const;
    std::string ToString() const;

    rapidjson::Document* GetDoc();

protected:
    rapidjson::Document* m_doc;
    rapidjson::Value*    m_value;
};

class JsonRoot : public JsonObject 
{
public:
    JsonRoot();
    ~JsonRoot();

private:
    rapidjson::Document m_sdoc;
};

